package com.zbkj.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zbkj.common.constants.Constants;
import com.zbkj.common.constants.ProductConstants;
import com.zbkj.common.constants.RedisConstants;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.model.admin.SystemAdmin;
import com.zbkj.common.model.cdkey.CardSecret;
import com.zbkj.common.model.cdkey.CdkeyLibrary;
import com.zbkj.common.model.order.RechargeOrder;
import com.zbkj.common.model.product.ProductAttrValue;
import com.zbkj.common.model.product.ProductCategory;
import com.zbkj.common.model.wechat.video.PayComponentShopBrand;
import com.zbkj.common.page.CommonPage;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.ProductCategoryRequest;
import com.zbkj.common.request.ProductCategorySearchRequest;
import com.zbkj.common.result.CommonResultCode;
import com.zbkj.common.result.ProductResultCode;
import com.zbkj.common.utils.CrmebUtil;
import com.zbkj.common.utils.RedisUtil;
import com.zbkj.common.utils.SecurityUtil;
import com.zbkj.common.vo.ProCategoryCacheTree;
import com.zbkj.common.vo.ProCategoryCacheVo;
import com.zbkj.service.dao.ProductCategoryDao;
import com.zbkj.service.service.*;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * ProductCategoryServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 */
@Service
public class ProductCategoryServiceImpl extends ServiceImpl<ProductCategoryDao, ProductCategory> implements ProductCategoryService {

    @Resource
    private ProductCategoryDao dao;

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private SystemAttachmentService systemAttachmentService;
    @Autowired
    private ProductService productService;
    @Autowired
    private ProductBrandCategoryService productBrandCategoryService;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private CouponService couponService;

    /**
     * 获取分类列表
     */
    @Override
    public List<ProductCategory> getAdminList() {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductCategory::getIsDel, false);
        lqw.orderByDesc(ProductCategory::getSort);
        lqw.orderByAsc(ProductCategory::getId);
        return dao.selectList(lqw);
    }

    @Override
    public List<ProductCategory> getAdminAllList(ProductCategorySearchRequest request) {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductCategory::getIsDel, false);
        lqw.eq(Objects.nonNull(request.getId()), ProductCategory::getId, request.getId());
        lqw.eq(Objects.nonNull(request.getIsShow()), ProductCategory::getIsShow, request.getIsShow());
        lqw.eq(Objects.nonNull(request.getPid()), ProductCategory::getPid, request.getPid());
        lqw.like(StringUtils.isNotBlank(request.getName()), ProductCategory::getName, request.getName());
        lqw.eq(Objects.nonNull(request.getLevel()), ProductCategory::getLevel, request.getLevel());
        lqw.orderByDesc(ProductCategory::getSort);
        lqw.orderByAsc(ProductCategory::getId);
        List<ProductCategory> categoryList = dao.selectList(lqw);
        for (ProductCategory category : categoryList) {
            lqw = Wrappers.lambdaQuery();
            lqw.eq(Objects.nonNull(request.getIsShow()), ProductCategory::getIsShow, request.getIsShow());
            lqw.eq(Objects.nonNull(category.getPid()), ProductCategory::getPid, category.getPid());
            lqw.eq(ProductCategory::getIsDel, false);
            List<ProductCategory> categoryChildrenList = dao.selectList(lqw);
            if (Objects.nonNull(categoryChildrenList) && categoryChildrenList.size()>0){
                category.setHasChildren(true);
            }
        }

        return categoryList;
    }

    @Override
    public PageInfo<ProductCategory> getAdminPageList(ProductCategorySearchRequest searchRequest) {
        Page<RechargeOrder> page = PageHelper.startPage(searchRequest.getPage(), searchRequest.getLimit());
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductCategory::getIsDel, false);
        lqw.orderByDesc(ProductCategory::getSort);
        lqw.orderByAsc(ProductCategory::getId);
        lqw.eq(Objects.nonNull(searchRequest.getIsShow()), ProductCategory::getIsShow, searchRequest.getIsShow());
        lqw.in(Objects.nonNull(searchRequest.getIsShows()), ProductCategory::getIsShow, searchRequest.getIsShows());
        List<ProductCategory> categoryList = dao.selectList(lqw);
        categoryList.stream().forEach(item -> {
            List<ProductCategory> listByPid = findAllParentListByPid(item.getId());
            if (listByPid.size()>0){
                Collections.reverse(listByPid);
                item.setParentName(org.apache.commons.lang3.StringUtils.join(listByPid.stream().map(ProductCategory::getName).collect(Collectors.toList()), "\\"));
            }
        });
        return CommonPage.copyPageInfo(page, categoryList);
    }

    @Override
    public ProductCategory getInfo(Integer id) {
        return dao.selectById(id);
    }

    @Override
    public PageInfo<ProductCategory> getXcxAdminList(ProductCategory category, PageParamRequest pageParamRequest) {
        Page<PayComponentShopBrand> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductCategory::getIsDel, false);
        lqw.eq(Objects.nonNull(category.getId()), ProductCategory::getId, category.getId());
        lqw.eq(Objects.nonNull(category.getLevel()), ProductCategory::getLevel, category.getLevel());
        lqw.eq(Objects.nonNull(category.getPid()), ProductCategory::getPid, category.getPid());
        lqw.like(StrUtil.isNotEmpty(category.getName()), ProductCategory::getName, category.getName());
        lqw.eq(ProductCategory::getIsShow, 1);
        lqw.orderByDesc(ProductCategory::getSort);
        lqw.orderByAsc(ProductCategory::getId);
        List<ProductCategory> categoryList = dao.selectList(lqw);
        return CommonPage.copyPageInfo(page, categoryList);
    }

    @Override
    public PageInfo<ProductCategory> getXcxAccuracyAdminList(ProductCategory category, PageParamRequest pageParamRequest) {
        Page<PayComponentShopBrand> page = PageHelper.startPage(pageParamRequest.getPage(), pageParamRequest.getLimit());
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductCategory::getIsDel, false);
        lqw.eq(Objects.nonNull(category.getId()), ProductCategory::getId, category.getId());
        lqw.eq(Objects.nonNull(category.getLevel()), ProductCategory::getLevel, category.getLevel());
        lqw.eq(Objects.nonNull(category.getPid()), ProductCategory::getPid, category.getPid());
        lqw.eq(StrUtil.isNotEmpty(category.getName()), ProductCategory::getName, category.getName());
        lqw.eq(ProductCategory::getIsShow, 1);
        lqw.orderByDesc(ProductCategory::getSort);
        lqw.orderByAsc(ProductCategory::getId);
        List<ProductCategory> categoryList = dao.selectList(lqw);
        return CommonPage.copyPageInfo(page, categoryList);
    }

    /**
     *
     *
     * @param request 添加参数
     * @return Boolean
     */
    @Override
    public Boolean add(ProductCategoryRequest request) {
        if (checkName(request.getName(), request.getPid())) {
            throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "分类名称已存在");
        }
        ProductCategory productCategory = new ProductCategory();
        BeanUtils.copyProperties(request, productCategory);
        productCategory.setId(null);
        productCategory.setPid(0);
        if (!request.getLevel().equals(1)) {
            if (request.getPid().equals(0)) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "子级菜单，父级ID不能为0");
            }
            ProductCategory category = getByIdException(request.getPid());
            if (category.getLevel() >= request.getLevel()) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "新增的商品分类层级异常");
            }
            productCategory.setPid(request.getPid());
        }
        if (StrUtil.isNotBlank(productCategory.getIcon())) {
            productCategory.setIcon(systemAttachmentService.clearPrefix(productCategory.getIcon()));
        }
        boolean save = save(productCategory);
        if (save) {
            redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY);
            redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_MERCHANT_LIST_KEY);
        }
        return save;
    }

    /**
     * 删除分类
     *
     * @param id 分类ID
     * @return Boolean
     * 删除时，需要判断分类是否被使用
     * 1.是否被品牌关联
     * 2.是否被商品使用
     * 后续改成如果1，2级分类，有子分类时无法删除
     */
    @Override
    public Boolean delete(Integer id) {
        ProductCategory category = getByIdException(id);
        if (category.getLevel() < 3) {
            List<ProductCategory> categoryList = findAllChildListByPid(category.getId(), category.getLevel());
            if (CollUtil.isNotEmpty(categoryList)) {
                throw new CrmebException(CommonResultCode.ERROR, "请先删除子级分类");
            }
        }
        // 判断是否有商品使用该分类
        if (productService.isUsePlatformCategory(category.getId())) {
            throw new CrmebException(ProductResultCode.PRODUCT_PLAT_CATEGORY_USED.setMessage("有商品使用该分类，无法删除"));
        }
        // 判断是否品牌关联该分类
        if (productBrandCategoryService.isExistCategory(category.getId())) {
            throw new CrmebException(ProductResultCode.PRODUCT_PLAT_CATEGORY_USED.setMessage("有品牌关联该分类，无法删除"));
        }
        category.setIsDel(true);
        Boolean update = transactionTemplate.execute(e -> {
            updateById(category);
            // 删除商品分类相关优惠券
            couponService.deleteByProCategoryId(category.getId());
            return Boolean.TRUE;
        });
        if (update) {
            redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY);
            redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_MERCHANT_LIST_KEY);
        }
        return update;
    }

    /**
     * 修改分类
     *
     * @param request 修改参数
     * @return Boolean
     */
    @Override
    public Boolean edit(ProductCategoryRequest request) {
        if (ObjectUtil.isNull(request.getId()) || ObjectUtil.isNull(request.getPid())) {
            throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "商品分类ID或Pid不能为空");
        }
        ProductCategory oldCategory = getByIdException(request.getId());
        if (!oldCategory.getName().equals(request.getName()) || !oldCategory.getPid().equals(request.getPid())) {
            if (checkName(request.getName(), request.getPid())) {
                throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "分类名称已存在");
            }
        }
        // 如果分类级别更改，三级分类修改时，需要判断是否有商品/品牌 使用该分类
        if (oldCategory.getLevel().equals(3) && !request.getLevel().equals(3)) {
            // 判断是否有商品使用该分类
            if (productService.isUsePlatformCategory(oldCategory.getId())) {
                throw new CrmebException(ProductResultCode.PRODUCT_PLAT_CATEGORY_USED.setMessage("有商品使用该分类，无法修改"));
            }
            // 判断是否品牌关联该分类
            if (productBrandCategoryService.isExistCategory(oldCategory.getId())) {
                throw new CrmebException(ProductResultCode.PRODUCT_PLAT_CATEGORY_USED.setMessage("有品牌关联该分类，无法修改"));
            }
        }

        ProductCategory category = new ProductCategory();
        BeanUtils.copyProperties(request, category);
        category.setPid(oldCategory.getPid());
        if (StrUtil.isNotBlank(category.getIcon())) {
            category.setIcon(systemAttachmentService.clearPrefix(category.getIcon()));
        }
        boolean update = updateById(category);
        if (update) {
            redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY);
            redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_MERCHANT_LIST_KEY);
        }
        return update;
    }

    /**
     * 修改分类显示状态
     *
     * @param id 分类ID
     * @return Boolean
     */
    @Override
    public Boolean updateShowStatus(Integer id) {
        ProductCategory category = getByIdException(id);
        List<ProductCategory> categoryList = new ArrayList<>();
        boolean showStatus = !(category.getIsShow()==1 ? true:false);
        if (!category.getLevel().equals(1) && showStatus) {
            ProductCategory parentCategory = getByIdException(category.getPid());
            if (parentCategory.getIsShow().equals(false)) {
                parentCategory.setIsShow(category.getIsShow());
                categoryList.add(parentCategory);
            }
            if (parentCategory.getLevel().equals(2)) {
                ProductCategory firstCategory = getByIdException(parentCategory.getPid());
                if (firstCategory.getIsShow().equals(false)) {
                    firstCategory.setIsShow(category.getIsShow());
                    categoryList.add(firstCategory);
                }
            }
        }

        category.setIsShow(category.getIsShow());
        categoryList.add(category);
        Boolean update = transactionTemplate.execute(e -> {
            updateBatchById(categoryList);
            if (category.getLevel().equals(2)) {
                updateChildShowStatus(category.getId(), showStatus);
            }
            if (category.getLevel().equals(1)) {
                List<ProductCategory> productCategoryList = findAllChildListByPid(category.getId(), category.getLevel());
                productCategoryList.forEach(c -> c.setIsShow(category.getIsShow()));
                updateBatchById(productCategoryList, 100);
            }
            return Boolean.TRUE;
        });

        if (update) {
            // 平台端缓存列表不受显示状态影响
            redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY);
            redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_MERCHANT_LIST_KEY);
        }
        return update;
    }

    /**
     * 更新子级显示状态
     *
     * @param pid 父级ID
     */
    private void updateChildShowStatus(Integer pid, Boolean showStatus) {
        LambdaUpdateWrapper<ProductCategory> wrapper = Wrappers.lambdaUpdate();
        wrapper.set(ProductCategory::getIsShow, showStatus);
        wrapper.eq(ProductCategory::getPid, pid);
        update(wrapper);
    }

    /**
     * 获取分类缓存树
     *
     * @return List<ProCategoryCacheVo>
     */
    @Override
    public List<ProCategoryCacheVo> getCacheTree(Integer isShow) {
        List<ProductCategory> categoryList = CollUtil.newArrayList();
        if (redisUtil.exists(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY)) {
            categoryList = redisUtil.get(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY);
        } else {
            LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
            lqw.eq(ProductCategory::getIsDel, false);
            lqw.eq(Objects.nonNull(isShow), ProductCategory::getIsShow, isShow);
            categoryList = dao.selectList(lqw);
            if (CollUtil.isEmpty(categoryList)) {
                return CollUtil.newArrayList();
            }
            redisUtil.set(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY, categoryList);
        }
        List<ProCategoryCacheVo> voList = categoryList.stream().map(e -> {
            ProCategoryCacheVo cacheVo = new ProCategoryCacheVo();
            BeanUtils.copyProperties(e, cacheVo);
            return cacheVo;
        }).collect(Collectors.toList());
        ProCategoryCacheTree categoryTree = new ProCategoryCacheTree(voList);
        return categoryTree.buildTree();
    }

    @Override
    public List<ProCategoryCacheVo> getCacheTreeOnlyThree(Integer isShow) {
        List<ProductCategory> categoryList = CollUtil.newArrayList();
//        if (redisUtil.exists(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY3)) {
//            categoryList = redisUtil.get(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY3);
//        } else {
            List<Object> levelList = new ArrayList<>();
            levelList.addAll(Arrays.asList(1, 2, 3));

            LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
            lqw.eq(ProductCategory::getIsDel, false);
            lqw.in(ProductCategory::getLevel, levelList);
            lqw.eq(Objects.nonNull(isShow), ProductCategory::getIsShow, isShow);
            categoryList = dao.selectList(lqw);
            if (CollUtil.isEmpty(categoryList)) {
                return CollUtil.newArrayList();
            }
            redisUtil.set(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY3, categoryList);
//        }
        List<ProCategoryCacheVo> voList = categoryList.stream().map(e -> {
            ProCategoryCacheVo cacheVo = new ProCategoryCacheVo();
            BeanUtils.copyProperties(e, cacheVo);
            return cacheVo;
        }).collect(Collectors.toList());
        ProCategoryCacheTree categoryTree = new ProCategoryCacheTree(voList);
        return categoryTree.buildTree();
    }

    /**
     * 商户端分类缓存树
     *
     * @return List<ProCategoryCacheVo>
     */
    @Override
    public List<ProCategoryCacheVo> getMerchantCacheTree() {
        List<ProductCategory> categoryList = CollUtil.newArrayList();
        if (redisUtil.exists(RedisConstants.PRODUCT_CATEGORY_CACHE_MERCHANT_LIST_KEY)) {
            categoryList = redisUtil.get(RedisConstants.PRODUCT_CATEGORY_CACHE_MERCHANT_LIST_KEY);
        } else {
            LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
            lqw.eq(ProductCategory::getIsShow, true);
            lqw.eq(ProductCategory::getIsDel, false);
            categoryList = dao.selectList(lqw);
            if (CollUtil.isEmpty(categoryList)) {
                return CollUtil.newArrayList();
            }
            redisUtil.set(RedisConstants.PRODUCT_CATEGORY_CACHE_MERCHANT_LIST_KEY, categoryList);
        }
        List<ProCategoryCacheVo> voList = categoryList.stream().map(e -> {
            ProCategoryCacheVo cacheVo = new ProCategoryCacheVo();
            BeanUtils.copyProperties(e, cacheVo);
            return cacheVo;
        }).collect(Collectors.toList());
        ProCategoryCacheTree categoryTree = new ProCategoryCacheTree(voList);
        return categoryTree.buildTree();
    }

    /**
     * 根据菜单id获取所有下级对象
     *
     * @param pid   菜单id
     * @param level 分类级别
     * @return List<ProductCategory>
     */
    @Override
    public List<ProductCategory> findAllChildListByPid(Integer pid, Integer level) {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductCategory::getPid, pid);
        lqw.eq(ProductCategory::getIsDel, false);
        if (!level.equals(1)) {
            return dao.selectList(lqw);
        }
        // level == 1
        List<ProductCategory> categoryList = dao.selectList(lqw);
        if (CollUtil.isEmpty(categoryList)) {
            return categoryList;
        }
        List<Integer> pidList = categoryList.stream().map(ProductCategory::getId).collect(Collectors.toList());
        lqw.clear();
        lqw.in(ProductCategory::getPid, pidList);
        lqw.eq(ProductCategory::getIsDel, false);
        List<ProductCategory> childCategoryList = dao.selectList(lqw);
        categoryList.addAll(childCategoryList);
        return categoryList;
    }

    /**
     * 根据菜单id获取所有下级对象
     *
     * @param id   菜单id
     * @return List<ProductCategory>
     */
    @Override
    public List<ProductCategory> findAllParentListByPid(Integer id) {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.eq(ProductCategory::getId, id);
        lqw.eq(ProductCategory::getIsDel, false);
        ProductCategory category = dao.selectOne(lqw);

        Boolean returnFalg = true;
        List<ProductCategory> categoryList = new ArrayList<>();
        while (returnFalg){
            if (category.getPid().equals(0)){
                //说明上面已经没了
                returnFalg = false;
            }else {
                lqw = Wrappers.lambdaQuery();
                lqw.eq(ProductCategory::getIsDel, false);
                lqw.eq(ProductCategory::getId, category.getPid());
                category = dao.selectOne(lqw);
                if (Objects.isNull(category)){
                    returnFalg = false;
                }else categoryList.add(category);
            }
        }
        return categoryList;
    }

    /**
     * 获取一级分类数据
     */
    @Override
    public List<ProCategoryCacheVo> getFrontFirstCategory() {
        List<ProCategoryCacheVo> cacheVoList = getMerchantCacheTree();
        return cacheVoList.stream().filter(e -> e.getLevel().equals(1)).collect(Collectors.toList());
    }

    /**
     * 获取首页第三级分类数据
     *
     * @param firstId 第一级分类id
     */
    @Override
    public List<ProductCategory> getHomeThirdCategory(Integer firstId) {
        return getThirdCategoryByFirstId(firstId, 9);
    }

    /**
     * 获取第三级分类数据
     *
     * @param firstId 第一级分类id
     * @param limit   查询数量，0全部
     */
    @Override
    public List<ProductCategory> getThirdCategoryByFirstId(Integer firstId, Integer limit) {
        return dao.getThirdCategoryByFirstId(firstId, limit);
    }

    /**
     * 获取相关层级分类数据
     * @param firstId 第一级分类id
     * @param level 层级
     */
    @Override
    public List<ProductCategory> getLevelCategoryById(Integer firstId, Integer level) {
        return dao.getLevelCategoryById(firstId, level);
    }

    /**
     * 通过分类id列表获取分类map
     *
     * @param cateIdList 分类id列表
     * @return Map
     */
    @Override
    public Map<Integer, ProductCategory> getMapByIdList(List<Integer> cateIdList) {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.select(ProductCategory::getId, ProductCategory::getName);
        lqw.in(ProductCategory::getId, cateIdList);
        List<ProductCategory> categoryList = dao.selectList(lqw);
        Map<Integer, ProductCategory> categoryMap = CollUtil.newHashMap();
        categoryList.forEach(c -> {
            categoryMap.put(c.getId(), c);
        });
        return categoryMap;
    }

    /**
     * 获取分类名称通过Ids
     *
     * @param proCategoryIds 分类ID字符，逗号分隔
     * @return 分类名称字符，逗号分隔
     */
    @Override
    public String getNameStrByIds(String proCategoryIds) {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.select(ProductCategory::getName);
        lqw.in(ProductCategory::getId, CrmebUtil.stringToArray(proCategoryIds));
        List<ProductCategory> categoryList = dao.selectList(lqw);
        return categoryList.stream().map(ProductCategory::getName).collect(Collectors.joining(","));
    }

    /**
     * 通过子ID获取所有父ID
     * @param childIdList 子分类ID
     */
    @Override
    public List<Integer> findParentIdByChildIds(List<Integer> childIdList) {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.in(ProductCategory::getId, childIdList);
        List<ProductCategory> list = dao.selectList(lqw);
        return list.stream().map(ProductCategory::getPid).collect(Collectors.toList());
    }

    @Override
    public List<ProductCategory> findByIdList(List<Integer> idList) {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.in(ProductCategory::getId, idList);
        return dao.selectList(lqw);
    }

    private ProductCategory getByIdException(Integer id) {
        ProductCategory category = getById(id);
        if (ObjectUtil.isNull(category) || category.getIsDel()) {
            throw new CrmebException(ProductResultCode.PRODUCT_PLAT_CATEGORY_NOT_EXIST);
        }
        return category;
    }

    /**
     * 校验分类名称
     *
     * @param name 分类名称
     * @return Boolean
     */
    private Boolean checkName(String name, Integer pid) {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.select(ProductCategory::getId);
        lqw.eq(ProductCategory::getName, name);
        lqw.eq(ProductCategory::getIsDel, false);
        lqw.eq(ProductCategory::getPid, pid);
        lqw.last(" limit 1");
        ProductCategory productCategory = dao.selectOne(lqw);
        return ObjectUtil.isNotNull(productCategory) ? Boolean.TRUE : Boolean.FALSE;
    }


    /**
     * 导入商品分类
     * @param file 导入文件
     * @return 导入结果
     */
    @Override
    public Boolean addImportExcel(MultipartFile file){
        String type = FileUtil.extName(file.getOriginalFilename());
        if (!"xlsx".equals(type) && !"xls".equals(type)) {
            throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "请提交正确的excel文件");
        }
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            log.error("导入商品分类获取文件流失败", e);
            throw new CrmebException("导入商品分类获取文件流失败");
        }
        try {
            Workbook workbook = WorkbookFactory.create(inputStream);
            Iterator<Sheet> sheetIterator = workbook.sheetIterator();
            while (sheetIterator.hasNext()) {
                //获取每行的数据
                Sheet sheet = sheetIterator.next();
                Iterator<Row> rowIterator = sheet.rowIterator();
                while (rowIterator.hasNext()){
                    Row row = rowIterator.next();
                    //获取一级商品分类
                    Cell cell1 = row.getCell(0);
                    String firstLevelName = cell1.getStringCellValue();
                    if (StrUtil.isEmpty(firstLevelName)) break;
                    ProductCategory firstCategory = checkCategoryExist(firstLevelName, 1);
                    if (Objects.isNull(firstCategory)) firstCategory = saveCategory(firstLevelName, 1, 0, 0);
                    //获取二级商品分类
                    Cell cell2 = row.getCell(1);
                    String secondLevelName = cell2.getStringCellValue();
                    if (StrUtil.isEmpty(secondLevelName)) break;
                    ProductCategory secondCategory = checkCategoryExist(secondLevelName, 2);
                    if (Objects.isNull(secondCategory)) secondCategory = saveCategory(secondLevelName, 2, firstCategory.getId(), 0);
                    //获取三级商品分类
                    Cell cell3 = row.getCell(2);
                    String threeLevelName = cell3.getStringCellValue();
                    if (StrUtil.isEmpty(threeLevelName)) break;
                    ProductCategory threeCategory = checkCategoryExist(threeLevelName, 3);
                    if (Objects.isNull(threeCategory)) threeCategory = saveCategory(threeLevelName, 3, secondCategory.getId(), 0);

                    Iterator<Cell> cellIterator = row.cellIterator();
                    Integer cellNum = 0;
                    while (cellIterator.hasNext()){
                        if (cellNum<3) {
                            cellIterator.next();
                            cellNum++;
                            continue;
                        }
                        //获取四级商品分类
                        Cell cell4 = cellIterator.next();
                        String fourLevelName = cell4.getStringCellValue();
                        if (StrUtil.isEmpty(fourLevelName)) break;
                        ProductCategory fourCategory = checkCategoryExist(fourLevelName, 4);
                        if (Objects.isNull(fourCategory)) saveCategory(fourLevelName, 4, threeCategory.getId(), cellNum);
                    }
                }
            }
        }catch (Exception e){
            log.error("导入商品分类获取文件失败", e);
            throw new CrmebException("请检查文件格式");
        }
        redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY);
        return Boolean.TRUE;
    }
//    @Override
//    public Boolean addImportExcel(MultipartFile file){
//        String type = FileUtil.extName(file.getOriginalFilename());
//        if (!"xlsx".equals(type) && !"xls".equals(type)) {
//            throw new CrmebException(CommonResultCode.VALIDATE_FAILED, "请提交正确的excel文件");
//        }
//        InputStream inputStream = null;
//        try {
//            inputStream = file.getInputStream();
//        } catch (IOException e) {
//            log.error("导入商品分类获取文件流失败", e);
//            throw new CrmebException("导入商品分类获取文件流失败");
//        }
//        try {
//            //获取一级商品分类
//            String firstLevelName = file.getOriginalFilename().split(".xls")[0];
//            if (StrUtil.isEmpty(firstLevelName)) return false;
//            ProductCategory firstCategory = checkCategoryExist(firstLevelName, 1);
//            if (Objects.isNull(firstCategory)) firstCategory = saveCategory(firstLevelName, 1, 0, 0);
//
//            Workbook workbook = WorkbookFactory.create(inputStream);
//            Iterator<Sheet> sheetIterator = workbook.sheetIterator();
//            while (sheetIterator.hasNext()) {
//                //获取二级商品分类
//                Sheet sheet = sheetIterator.next();
//                String secondLevelName = sheet.getSheetName();
//                if (StrUtil.isEmpty(secondLevelName)) continue;
//                ProductCategory secondCategory = checkCategoryExist(secondLevelName, 2);
//                if (Objects.isNull(secondCategory)) secondCategory = saveCategory(secondLevelName, 2, firstCategory.getId(), 0);
//
//                //获取每行的数据
//                Iterator<Row> rowIterator = sheet.rowIterator();
//                while (rowIterator.hasNext()){
//                    Row row = rowIterator.next();
//                    //获取三级商品分类
//                    Cell cell = row.getCell(0);
//                    String threeLevelName = cell.getStringCellValue();
//                    if (StrUtil.isEmpty(threeLevelName)) break;
//                    ProductCategory threeCategory = checkCategoryExist(threeLevelName, 3);
//                    if (Objects.isNull(threeCategory)) threeCategory = saveCategory(threeLevelName, 3, secondCategory.getId(), 0);
//
//                    Iterator<Cell> cellIterator = row.cellIterator();
//                    Integer cellNum = 0;
//                    while (cellIterator.hasNext()){
//                        if (cellNum==0) {
//                            cellIterator.next();
//                            cellNum++;
//                            continue;
//                        }
//                        Cell cellFour = cellIterator.next();
//                        String fourLevelName = cellFour.getStringCellValue();
//                        if (StrUtil.isEmpty(fourLevelName)) break;
//                        ProductCategory fourCategory = checkCategoryExist(fourLevelName, 4);
//                        if (Objects.isNull(fourCategory)) saveCategory(fourLevelName, 4, threeCategory.getId(), cellNum);
//                    }
//                }
//            }
//        }catch (Exception e){
//            log.error("导入商品分类获取文件失败", e);
//            throw new CrmebException("请检查文件格式");
//        }
//        redisUtil.delete(RedisConstants.PRODUCT_CATEGORY_CACHE_LIST_KEY);
//        return Boolean.TRUE;
//    }

    //查询这个分类在当前层级是否存在
    private ProductCategory checkCategoryExist(String name, Integer level) {
        LambdaQueryWrapper<ProductCategory> lqw = Wrappers.lambdaQuery();
        lqw.select(ProductCategory::getId);
        lqw.eq(ProductCategory::getName, name);
        lqw.eq(ProductCategory::getIsDel, false);
        lqw.eq(ProductCategory::getLevel, level);
        lqw.last(" limit 1");
        ProductCategory productCategory = dao.selectOne(lqw);
        return productCategory;
    }

    //新增商品分类
    private ProductCategory saveCategory(String name, Integer level, Integer pid, Integer sort) {
        ProductCategory category = new ProductCategory();
        category.setPid(pid);
        category.setName(name);
        category.setLevel(level);
        category.setSort(sort);
        category.setIsShow(1);
        return dao.insert(category)>0 ? category:null;
    }
}

